/**
 * @Author: Jiang Zhongxun
 * @Date: 2024-10-03 20:52:24
 * @FilePath: /Socket/practiceProject/src/client/client.c
 * @Description:
 */
#include "../../include/client/client.h"
#include "../../include/client/adminOpt.h"
#include "../../include/client/menu.h"
#include "../../include/client/userOpt.h"
#include "../../include/db/dbDefinition.h"
#include "../../include/db/dbOperation.h"
#include "../../include/utils/utils.h"

const int PORT = 6666; // 端口号

int is_login = 0; // 0 表示未登录，1 表示已登录

/**
 * @description: 客户端通信
 * @param {int} sockfd 套接字
 * @return {*} 成功返回0，失败返回-1
 */
int tcpClientCom(int sockfd)
{
    if (sockfd < 0)
    {
        printf("sockfd is error!\n");
        return -1;
    }
    char buf[64] = {0};
    char initFlag[] = "init";      // 业务种类
    char initOption[20] = {0};     // 业务名称
    char msgFromServer[128] = {0}; // 接收服务端消息
    int recvSize;
    char userName[20] = {0};
    char passwd[20] = {0};
    int totalReceived = 0;
    // 只在未登录时展示初始菜单
    if (!is_login)
    {
        // 展示初始菜单
        initMenu();
        // 将处理的业务名称发送给服务器【login \ register \ quit】
        printf("请输入业务名称[login \\ register \\ quit]: ");
        scanf("%s", initOption);
        if (0 == strncasecmp(initOption, "quit", 4))
        {
            printf("退出平台成功!\n");
            return -1;
        }
        sprintf(buf, "%s@%s", initFlag, initOption);
        // 将业务种类和业务名称，发给服务器处理请求
        send(sockfd, buf, sizeof(buf), 0);
        printf("发送业务名称给服务端, 成功!\n");
    }
    // 判断客户端的业务种类
    // 登录业务
    if (0 == strncasecmp(initOption, "login", 5))
    {
        printf("请输入用户名: ");
        scanf("%s", userName);
        printf("请输入密码: ");
        scanf("%s", passwd);
        // 发送用户名密码给服务端
        bzero(buf, sizeof(buf));
        sprintf(buf, "%s@%s@%s", initOption, userName, passwd);
        printf("buf = %s\n", buf);
        send(sockfd, buf, sizeof(buf), 0);
        printf("发送业务名称给服务端, 成功!\n");
        // 接收服务端处理登录业务的结果
        totalReceived = 0;
        bzero(msgFromServer, sizeof(msgFromServer));
        while (totalReceived < sizeof(msgFromServer))
        {
            int bytesLeft = sizeof(msgFromServer) - totalReceived;
            // recvSize = recv(sockfd, msgFromServer, sizeof(msgFromServer), 0);
            recvSize = recv(sockfd, msgFromServer + totalReceived, bytesLeft, 0);
            if (recvSize > 0)
            {
                totalReceived += recvSize;
                // 当接收到的数据量达到缓冲区大小时，手动添加结束符
                if (totalReceived >= sizeof(msgFromServer))
                {
                    msgFromServer[sizeof(msgFromServer) - 1] = '\0'; // 强制结束符
                }
                printf("recvSize: %d, totalReceived: %d\n", recvSize, totalReceived);
            }
            else if (0 == recvSize)
            {
                printf("client服务器已下线退出!\n");
                return -1;
            }
            else if (recvSize < 0)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    // 没有数据可读取，继续等待其他事件
                    usleep(1000); // 等待一小段时间后再继续尝试接收
                    continue;     // 继续下一轮循环，等待更多数据
                }
                else
                {
                    perror("recv server login data error");
                    return -1; // 处理其他错误
                }
            }
        }
        // 这里需要确保你在后续操作中处理字符串时避免超出
        printf("client login Final buf: %s\n", msgFromServer); // 打印最终的 buf 内容
        printf("client login totalReceived = %d\n", totalReceived);
        printf("msgFromServer = %s\n", msgFromServer);
        // 解析数据
        char *loginedRes[4] = {NULL};
        if (totalReceived == 0 || msgFromServer[0] == '\0')
        {
            printf("接收到的 buf 为空，终止操作。\n");
            return -1;
        }
        parseStringUtil(msgFromServer, loginedRes);
        if ((0 == strncasecmp("login", loginedRes[0], 5)) && (0 == strncasecmp("Lucky", loginedRes[1], 5)))
        {
            // 登录成功
            printf("用户【%s】登录成功!\n", userName);
            is_login = 1; // 设置登录标识
            if (0 == strcmp(userName, "root"))
            {
                while (1)
                {
                    // 管理员登录
                    adminMenu();
                    int ret = adminTcpClientCom(sockfd);
                    if (ret != 0)
                    {
                        is_login = 0;
                        break;
                    }
                }
            }
            else
            {
                while (1)
                {
                    // 普通用户登录
                    userMenu();
                    int ret = userTcpClientCom(sockfd, userName);
                    if (ret != 0)
                    {
                        is_login = 0;
                        break;
                    }
                }
            }
        }
        else if ((0 == strncasecmp("login", loginedRes[0], 5)) && (0 == strncasecmp("Sorry", loginedRes[1], 5)))
        {
            // 登录失败，判断失败原因
            int logSta = atoi(loginedRes[2]);
            if (100 == logSta)
            {
                printf("用户名不存在! 请先进行注册!\n");
                return -1;
            }
            else if (200 == logSta)
            {
                printf("用户密码错误!\n");
                return -1;
            }
        }
    }
    // 注册业务
    else if (0 == strncasecmp(initOption, "register", 8))
    {
        printf("请输入用户名: ");
        scanf("%s", userName);
        printf("请输入密码: ");
        scanf("%s", passwd);
        // 发送用户名密码给服务端
        bzero(buf, sizeof(buf));
        sprintf(buf, "%s@%s@%s", initOption, userName, passwd);
        send(sockfd, buf, sizeof(buf), 0);
        printf("发送业务名称给服务端, 成功!\n");
        // 接收服务端处理注册业务的结果
        totalReceived = 0;
        bzero(msgFromServer, sizeof(msgFromServer));
        while (totalReceived < sizeof(msgFromServer))
        {
            int bytesLeft = sizeof(msgFromServer) - totalReceived;
            // recvSize = recv(sockfd, msgFromServer, sizeof(msgFromServer), 0);
            recvSize = recv(sockfd, msgFromServer + totalReceived, bytesLeft, 0);
            if (recvSize > 0)
            {
                totalReceived += recvSize;
                // 当接收到的数据量达到缓冲区大小时，手动添加结束符
                if (totalReceived >= sizeof(msgFromServer))
                {
                    msgFromServer[sizeof(msgFromServer) - 1] = '\0'; // 强制结束符
                }
                printf("recvSize: %d, totalReceived: %d\n", recvSize, totalReceived);
            }
            else if (0 == recvSize)
            {
                printf("client服务器已下线退出!\n");
                return -1;
            }
            else if (recvSize < 0)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    // 没有数据可读取，继续等待其他事件
                    usleep(1000); // 等待一小段时间后再继续尝试接收
                    continue;     // 继续下一轮循环，等待更多数据
                }
                else
                {
                    perror("recv server register data error");
                    return -1; // 处理其他错误
                }
            }
        }
        // 这里需要确保你在后续操作中处理字符串时避免超出
        printf("client register Final buf: %s\n", msgFromServer); // 打印最终的 buf 内容
        printf("client register totalReceived = %d\n", totalReceived);
        printf("msgFromServer = %s\n", msgFromServer);
        // 解析数据
        char *registerRes[4] = {NULL};
        if (totalReceived == 0 || msgFromServer[0] == '\0')
        {
            printf("接收到的 buf 为空，终止操作。\n");
            return -1;
        }
        parseStringUtil(msgFromServer, registerRes);
        if ((0 == strncasecmp("register", registerRes[0], 8)) && (0 == strncasecmp("Lucky", registerRes[1], 5)))
        {
            // 注册成功
            printf("用户名注册成功, 请执行登录!\n");
            is_login = 0; // 设置登录标识
        }
        else if ((0 == strncasecmp("register", registerRes[0], 8)) && (0 == strncasecmp("Sorry", registerRes[1], 5)))
        {
            // 注册失败
            int regSta = atoi(registerRes[2]);
            if (100 == regSta)
            {
                printf("注册失败,请稍后再试!\n");
                return -1;
            }
            else if (200 == regSta)
            {
                printf("用户名已存在! 请直接登录或重新注册!\n");
                return -1;
            }
            is_login = 0; // 设置登录标识
        }
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int sockfd, temp_res;
    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        return -1;
    }
    printf("sockfd ok!\n");
    // 设置服务器地址和端口号
    struct sockaddr_in serverAddr;          // 定义地址信息结构体变量
    bzero(&serverAddr, sizeof(serverAddr)); // 清空
    serverAddr.sin_family = AF_INET;        // 地址族
    // serverAddr.sin_port = htons((short)atoi(argv[2]));   // 端口号
    // serverAddr.sin_addr.s_addr = inet_addr(argv[1]);     // IP地址
    serverAddr.sin_port = htons(PORT);                   // 端口号 6666
    serverAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // IP地址 127.0.0.1
    // 发起连接请求
    temp_res = connect(sockfd, (struct sockaddr *)&serverAddr, (socklen_t)sizeof(serverAddr));
    if (temp_res < 0)
    {
        perror("client connect server error");
        close(sockfd);
        return -1;
    }
    printf("connect ok!\n");
    // 通信
    while (1)
    {
        if (tcpClientCom(sockfd) < 0)
        {
            break;
        }
    }
    // 关闭套接字
    close(sockfd);

    return 0;
}
